#!/bin/bash
# Wrapper script to correctly load up the percpu_var.ko module.
name=$(basename $0)

[[ -f /boot/config-$(uname -r) ]] && { # at least on x86[_64]
  grep -w "CONFIG_PROVE_LOCKING=y" /boot/config-$(uname -r) >/dev/null 2>&1
  [[ $? -ne 0 ]] && echo "${name}: WARNING! You're running this on a kernel without lockdep (CONFIG_PROVE_LOCKING) enabled"
}

DEADLOCK=0
[[ $# -ne 1 ]] && {
   echo "Usage: ${name} 0|1
 0 : run normally, take locks in the right (documented) order
 1 : run abnormally, take locks in the WRONG order, causing an AB-BA deadlock"
   exit 1
}
[[ $1 -eq 1 ]] && DEADLOCK=1

# !WARNING! This is considered a hack.
# As sched_setaffinity() isn't exported, we don't have access to it
# within this kernel module. So, here we resort to a hack: 
# a) Until 5.7, we could directly use the kallsyms_lookup_name() function
#    (which works when CONFIG_KALLSYMS is defined) to retrieve the function
#    pointer, and subsequently call the function via it's pointer (with 'C'
#    what you do is only limited by your imagination :).
# b) From 5.7 on, the kernel devs unexported the kallsyms_lookup_name()!
#    (Rationale: https://lwn.net/Articles/813350/). 
#
# So, with it gone, or not, we now simply use this approach:
#  A helper script (this one!) greps the sched_setaffinity()
#  address and passes it to the module as a parameter! There, we equate it to
#  the expected function signature - that of sched_setaffinity() - and use it.
# *Not* pedantically right, but hey, it works. Don't do this in production.
#
KMOD=deadlock_eg_AB-BA
KFUNC=sched_setaffinity
KFUNC_PTR=0x$(sudo grep -w "T ${KFUNC}" /proc/kallsyms |awk '{print $1}')
[[ -z "${KFUNC_PTR}" ]] && {
  echo "${name}: lookup of /proc/kallsyms failed, aborting..."
  exit 1
}
echo "sched_setaffinity() on $(uname -r): KFUNC_PTR=${KFUNC_PTR}
WARNING! this is certainly an info-leak! Don't do stuff like this in production."

make clean
make || exit 1
sudo rmmod ${KMOD} 2>/dev/null
sudo dmesg -C

if [[ ${DEADLOCK} -eq 1 ]] ; then
	sudo insmod ./${KMOD}.ko func_ptr=${KFUNC_PTR} lock_ooo=1
else
	sudo insmod ./${KMOD}.ko func_ptr=${KFUNC_PTR}
fi
sudo dmesg
